﻿using System;
using System.Collections.Generic;
using System.Text;

namespace gsl_runtime_sdk
{
    public class math_operator
    {
        public static string ToPHPmath(string GSL)
        {

        }
        public static string ToJavamath(string GSL)
        {

        }
        public static string FromPHPmath(string GSL)
        {

        }
        public static List<Variable> Compile(string[] code)
        {
            List<Variable> return_vars = new List<Variable>();

            List<Variable> var_one = new List<Variable>();
            List<string> Operations = new List<string>();
            List<Variable> var_two = new List<Variable>();


            int i = 0;
            string FirstVar = "";
            string SecondVar = "";
            string operand = "";
            foreach (string str in code)
            {
                Variable temp_v = new Variable();

                if (FirstVar == "")
                {
                    temp_v.Value = str;
                    var_one.Add(temp_v);
                    FirstVar = str;
                }
                else if (operand == "" && code.Length == 2)
                {
                    operand = str;
                    SecondVar = (operand == "++" ? "1" : (operand == "--" ? "1" : str));
                    temp_v.Value = SecondVar;
                    var_two.Add(temp_v);
                    Operations.Add(operand);
                    return_vars.Add(DoOperation(var_one[0], operand, var_two[0]));

                    FirstVar = "";
                    SecondVar = "";
                    operand = "";

                    Operations.Clear();
                    var_one.Clear();
                    var_two.Clear();
                }
                else if (operand == "" && code.Length == 3)
                    operand = str;
                else if (SecondVar == "")
                {
                    temp_v.Value = str;
                    var_two.Add(temp_v);
                    SecondVar = (operand == "++" ? "1" : (operand == "--" ? "1" : str));
                    Operations.Add(operand);
                    return_vars.Add(DoOperation(var_one[0], operand, var_two[0]));

                    FirstVar = "";
                    SecondVar = "";
                    operand = "";

                    Operations.Clear();
                    var_one.Clear();
                    var_two.Clear();
                }
                i++;
            }
            return return_vars;
        }
        public static Variable DoOperation(Variable One, string code, Variable Two)
        {
            //One.SetType();
            Variable return_val = One;
            switch (code)
            {
                case "==":
                    return_val.Value = (One.vtype == Variable.var_type.Bool ? (One.ToBool() == Two.ToBool() ? "true" : "false") :
                    (One.vtype == Variable.var_type.Integer ? (One.ToInteger() == Two.ToInteger() ? "true" : "false") :
                    (One.vtype == Variable.var_type.Double ? (One.ToDouble() == Two.ToDouble() ? "true" : "false") :
                    (One.vtype == Variable.var_type.String ? (One.Value == Two.Value ? "true" : "false") :
                    (One.vtype == Variable.var_type.Float ? (One.ToFloat() == Two.ToFloat() ? "true" : "false") : "-100")))));
                    break;
                case "=":
                    return_val.Value = Two.Value;
                    break;
                case "++":
                    return_val.Value = (One.vtype == Variable.var_type.Bool ? ("-101") :
                    (One.vtype == Variable.var_type.Integer ? "" + (One.ToInteger() + Two.ToInteger()) :
                    (One.vtype == Variable.var_type.Double ? "" + (One.ToDouble() + Two.ToDouble()) :
                    (One.vtype == Variable.var_type.Float ? "" + (One.ToFloat() + Two.ToFloat()) : "-100"))));
                    break;
                case "--":
                    return_val.Value = (One.vtype == Variable.var_type.Bool ? ("-101") :
                    (One.vtype == Variable.var_type.Integer ? "" + (One.ToInteger() - Two.ToInteger()) :
                    (One.vtype == Variable.var_type.Double ? "" + (One.ToDouble() - Two.ToDouble()) :
                    (One.vtype == Variable.var_type.Float ? "" + (One.ToFloat() - Two.ToFloat()) : "-100"))));
                    break;
                case "+":
                    return_val.Value = (One.vtype == Variable.var_type.Bool ? ("-101") :
                    (One.vtype == Variable.var_type.Integer ? "" + (One.ToInteger() + Two.ToInteger()) :
                    (One.vtype == Variable.var_type.String ? (One.Value + Two.Value) :
                    (One.vtype == Variable.var_type.Double ? "" + (One.ToDouble() + Two.ToDouble()) :
                    (One.vtype == Variable.var_type.Float ? "" + (One.ToFloat() + Two.ToFloat()) : "-100")))));
                    break;
                case "-":
                    return_val.Value = (One.vtype == Variable.var_type.Bool ? ("-101") :
                    (One.vtype == Variable.var_type.Integer ? "" + (One.ToInteger() - Two.ToInteger()) :
                    (One.vtype == Variable.var_type.Double ? "" + (One.ToDouble() - Two.ToDouble()) :
                    (One.vtype == Variable.var_type.Float ? "" + (One.ToFloat() - Two.ToFloat()) : "-100"))));
                    break;
                case "<":
                    return_val.Value = (One.vtype == Variable.var_type.Bool ? ("-101") :
                    (One.vtype == Variable.var_type.Integer ? "" + (One.ToInteger() < Two.ToInteger()) :
                    (One.vtype == Variable.var_type.Double ? "" + (One.ToDouble() < Two.ToDouble()) :
                    (One.vtype == Variable.var_type.Float ? "" + (One.ToFloat() < Two.ToFloat()) : "-100"))));
                    break;
                case "<=":
                    return_val.Value = (One.vtype == Variable.var_type.Bool ? ("-101") :
                    (One.vtype == Variable.var_type.Integer ? "" + (One.ToInteger() <= Two.ToInteger()) :
                    (One.vtype == Variable.var_type.Double ? "" + (One.ToDouble() <= Two.ToDouble()) :
                    (One.vtype == Variable.var_type.Float ? "" + (One.ToFloat() <= Two.ToFloat()) : "-100"))));
                    break;
                case ">":
                    return_val.Value = (One.vtype == Variable.var_type.Bool ? ("-101") :
                    (One.vtype == Variable.var_type.Integer ? "" + (One.ToInteger() > Two.ToInteger()) :
                    (One.vtype == Variable.var_type.Double ? "" + (One.ToDouble() > Two.ToDouble()) :
                    (One.vtype == Variable.var_type.Float ? "" + (One.ToFloat() > Two.ToFloat()) : "-100"))));
                    break;
                case ">=":
                    return_val.Value = (One.vtype == Variable.var_type.Bool ? ("-101") :
                    (One.vtype == Variable.var_type.Integer ? "" + (One.ToInteger() >= Two.ToInteger()) :
                    (One.vtype == Variable.var_type.Double ? "" + (One.ToDouble() >= Two.ToDouble()) :
                    (One.vtype == Variable.var_type.Float ? "" + (One.ToFloat() >= Two.ToFloat()) : "-100"))));
                    break;
                case "+=":
                    return_val.Value = (One.vtype == Variable.var_type.Bool ? ("-101") :
                    (One.vtype == Variable.var_type.Integer ? "" + (One.ToInteger() + Two.ToInteger()) :
                    (One.vtype == Variable.var_type.Double ? "" + (One.ToDouble() + Two.ToDouble()) :
                    (One.vtype == Variable.var_type.String ? (One.Value + Two.Value) :
                    (One.vtype == Variable.var_type.Float ? "" + (One.ToFloat() + Two.ToFloat()) : "-100")))));
                    break;
                case "-=":
                    return_val.Value = (One.vtype == Variable.var_type.Bool ? ("-101") :
                    (One.vtype == Variable.var_type.Integer ? "" + (One.ToInteger() - Two.ToInteger()) :
                    (One.vtype == Variable.var_type.Double ? "" + (One.ToDouble() - Two.ToDouble()) :
                    (One.vtype == Variable.var_type.Float ? "" + (One.ToFloat() - Two.ToFloat()) : "-100"))));
                    break;
                case "*":
                    return_val.Value = (One.vtype == Variable.var_type.Bool ? ("-101") :
                    (One.vtype == Variable.var_type.Integer ? "" + (One.ToInteger() * Two.ToInteger()) :
                    (One.vtype == Variable.var_type.Double ? "" + (One.ToDouble() * Two.ToDouble()) :
                    (One.vtype == Variable.var_type.Float ? "" + (One.ToFloat() * Two.ToFloat()) : "-100"))));
                    break;
                case "/":
                    return_val.Value = (One.vtype == Variable.var_type.Bool ? ("-101") :
                    (One.vtype == Variable.var_type.Integer ? "" + (One.ToInteger() / Two.ToInteger()) :
                    (One.vtype == Variable.var_type.Double ? "" + (One.ToDouble() / Two.ToDouble()) :
                    (One.vtype == Variable.var_type.Float ? "" + (One.ToFloat() / Two.ToFloat()) : "-100"))));
                    break;
                case "*=":
                    return_val.Value = (One.vtype == Variable.var_type.Bool ? ("-101") :
                    (One.vtype == Variable.var_type.Integer ? "" + (One.ToInteger() * Two.ToInteger()) :
                    (One.vtype == Variable.var_type.Double ? "" + (One.ToDouble() * Two.ToDouble()) :
                    (One.vtype == Variable.var_type.Float ? "" + (One.ToFloat() * Two.ToFloat()) : "-100"))));
                    break;
            }
            //return_val.SetType();
            return return_val;
        }

        public static bool IsMathOp(string code)
        {
            string[] CodeS = code.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            if (Variable.GetType(CodeS[0]) == (Variable.var_type.Integer & Variable.var_type.Double & Variable.var_type.Float) && Variable.GetType(CodeS[2]) == (Variable.var_type.Integer & Variable.var_type.Double & Variable.var_type.Float) && math_op.IsMathOperand(CodeS[1]))
                return true;
            else
                return false;
        }

        public static bool IsMathOperand(string code)
        {
            switch (code)
            {
                case "==":
                    return true;
                case "=":
                    return true;
                case "++":
                    return true;
                case "--":
                    return true;
                case "+":
                    return true;
                case "-":
                    return true;
                case "<":
                    return true;
                case "<=":
                    return true;
                case ">":
                    return true;
                case ">=":
                    return true;
                case "+=":
                    return true;
                case "-=":
                    return true;
                case "*":
                    return true;
                case "/":
                    return true;
                case "*=":
                    return true;
                default:
                    return false;
            }
        }
    }
}
